package com.ldzl.service.impl;

import com.ldzl.mapper.CkStockTakingMapper;
import com.ldzl.mapper.CkStockTakingResultMapper;
import com.ldzl.pojo.CkStockTaking;
import com.ldzl.pojo.CkStockTakingResult;
import com.ldzl.service.CkStockTakingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 库存盘点服务实现类
 */
@Service
public class CkStockTakingServiceImpl implements CkStockTakingService {

    @Autowired
    private CkStockTakingMapper ckStockTakingMapper;
    
    @Autowired
    private CkStockTakingResultMapper ckStockTakingResultMapper;

    /**
     * 查询库存盘点列表
     * 
     * @param ckStockTaking 库存盘点
     * @return 库存盘点集合
     */
    @Override
    public List<CkStockTaking> selectCkStockTakingList(CkStockTaking ckStockTaking) {
        return ckStockTakingMapper.selectCkStockTakingList(ckStockTaking);
    }

    /**
     * 查询库存盘点详细信息
     * 
     * @param takingId 库存盘点ID
     * @return 库存盘点
     */
    @Override
    public CkStockTaking selectCkStockTakingById(Long takingId) {
        CkStockTaking ckStockTaking = ckStockTakingMapper.selectCkStockTakingById(takingId);
        if (ckStockTaking != null) {
            List<CkStockTakingResult> details = ckStockTakingResultMapper.selectCkStockTakingResultByTakingId(takingId);
            ckStockTaking.setDetails(details);
        }
        return ckStockTaking;
    }

    /**
     * 新增库存盘点
     * 
     * @param ckStockTaking 库存盘点
     * @return 结果
     */
    @Override
    @Transactional
    public int insertCkStockTaking(CkStockTaking ckStockTaking) {
        ckStockTaking.setCreateTime(new Date());
        ckStockTaking.setStatus("0"); // 设置状态为草稿
        ckStockTaking.setApproveStatus("0"); // 设置审核状态为未提交
        
        // 设置盘点开始时间
        if (ckStockTaking.getStartTime() == null) {
            ckStockTaking.setStartTime(new Date());
        }
        
        int rows = ckStockTakingMapper.insertCkStockTaking(ckStockTaking);
        
        // 批量新增盘点明细
        if (ckStockTaking.getDetails() != null && !ckStockTaking.getDetails().isEmpty()) {
            for (CkStockTakingResult detail : ckStockTaking.getDetails()) {
                detail.setTakingId(ckStockTaking.getTakingId());
                detail.setCreateTime(new Date());
                detail.setCreateBy(ckStockTaking.getCreateBy());
                
                // 计算差异
                if (detail.getSystemQuantity() != null && detail.getActualQuantity() != null) {
                    detail.setDifferenceQuantity(detail.getActualQuantity().subtract(detail.getSystemQuantity()));
                }
                
                // 计算金额
                if (detail.getUnitPrice() != null) {
                    if (detail.getSystemQuantity() != null) {
                        detail.setSystemAmount(detail.getSystemQuantity().multiply(detail.getUnitPrice()));
                    }
                    if (detail.getActualQuantity() != null) {
                        detail.setActualAmount(detail.getActualQuantity().multiply(detail.getUnitPrice()));
                    }
                    if (detail.getDifferenceQuantity() != null) {
                        detail.setDifferenceAmount(detail.getDifferenceQuantity().multiply(detail.getUnitPrice()));
                    }
                }
            }
            ckStockTakingResultMapper.batchInsertCkStockTakingResult(ckStockTaking.getDetails());
        }
        
        return rows;
    }

    /**
     * 修改库存盘点
     * 
     * @param ckStockTaking 库存盘点
     * @return 结果
     */
    @Override
    @Transactional
    public int updateCkStockTaking(CkStockTaking ckStockTaking) {
        ckStockTaking.setUpdateTime(new Date());
        int rows = ckStockTakingMapper.updateCkStockTaking(ckStockTaking);
        
        // 如果有明细数据，先删除原有明细，再添加新明细
        if (ckStockTaking.getDetails() != null && !ckStockTaking.getDetails().isEmpty()) {
            ckStockTakingResultMapper.deleteCkStockTakingResultByTakingId(ckStockTaking.getTakingId());
            
            for (CkStockTakingResult detail : ckStockTaking.getDetails()) {
                detail.setTakingId(ckStockTaking.getTakingId());
                detail.setCreateTime(new Date());
                detail.setCreateBy(ckStockTaking.getUpdateBy());
                
                // 计算差异
                if (detail.getSystemQuantity() != null && detail.getActualQuantity() != null) {
                    detail.setDifferenceQuantity(detail.getActualQuantity().subtract(detail.getSystemQuantity()));
                }
                
                // 计算金额
                if (detail.getUnitPrice() != null) {
                    if (detail.getSystemQuantity() != null) {
                        detail.setSystemAmount(detail.getSystemQuantity().multiply(detail.getUnitPrice()));
                    }
                    if (detail.getActualQuantity() != null) {
                        detail.setActualAmount(detail.getActualQuantity().multiply(detail.getUnitPrice()));
                    }
                    if (detail.getDifferenceQuantity() != null) {
                        detail.setDifferenceAmount(detail.getDifferenceQuantity().multiply(detail.getUnitPrice()));
                    }
                }
            }
            ckStockTakingResultMapper.batchInsertCkStockTakingResult(ckStockTaking.getDetails());
        }
        
        return rows;
    }

    /**
     * 删除库存盘点信息
     * 
     * @param takingId 库存盘点ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCkStockTakingById(Long takingId) {
        // 检查盘点单状态，只有草稿状态才能删除
        CkStockTaking stockTaking = ckStockTakingMapper.selectCkStockTakingById(takingId);
        if (stockTaking != null && !"0".equals(stockTaking.getStatus())) {
            throw new RuntimeException("只能删除草稿状态的盘点单");
        }
        
        // 删除关联的盘点明细
        ckStockTakingResultMapper.deleteCkStockTakingResultByTakingId(takingId);
        return ckStockTakingMapper.deleteCkStockTakingById(takingId);
    }

    /**
     * 批量删除库存盘点
     * 
     * @param takingIds 需要删除的库存盘点ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCkStockTakingByIds(Long[] takingIds) {
        // 检查盘点单状态，只有草稿状态才能删除
        for (Long takingId : takingIds) {
            CkStockTaking stockTaking = ckStockTakingMapper.selectCkStockTakingById(takingId);
            if (stockTaking != null && !"0".equals(stockTaking.getStatus())) {
                throw new RuntimeException("只能删除草稿状态的盘点单");
            }
        }
        
        // 批量删除关联的盘点明细
        for (Long takingId : takingIds) {
            ckStockTakingResultMapper.deleteCkStockTakingResultByTakingId(takingId);
        }
        return ckStockTakingMapper.deleteCkStockTakingByIds(takingIds);
    }
    
    /**
     * 提交盘点单
     * 
     * @param takingId 盘点ID
     * @return 结果
     */
    @Override
    @Transactional
    public int submitCkStockTaking(Long takingId) {
        // 获取盘点单信息
        CkStockTaking stockTaking = ckStockTakingMapper.selectCkStockTakingById(takingId);
        if (stockTaking == null) {
            throw new RuntimeException("盘点单不存在");
        }
        
        // 检查盘点单状态，只有草稿状态才能提交
        if (!"0".equals(stockTaking.getStatus())) {
            throw new RuntimeException("只能提交草稿状态的盘点单");
        }
        
        // 检查盘点明细是否存在
        List<CkStockTakingResult> details = ckStockTakingResultMapper.selectCkStockTakingResultByTakingId(takingId);
        if (details == null || details.isEmpty()) {
            throw new RuntimeException("盘点单没有明细，不能提交");
        }
        
        // 冻结库存
        if ("Y".equals(stockTaking.getFrozenFlag())) {
            freezeInventory(takingId);
        }
        
        // 更新盘点单状态为进行中，审核状态为待审核
        return ckStockTakingMapper.updateStatus(takingId, "1", "1");
    }
    
    /**
     * 审核盘点单
     * 
     * @param ckStockTaking 盘点信息
     * @return 结果
     */
    @Override
    @Transactional
    public int approveCkStockTaking(CkStockTaking ckStockTaking) {
        ckStockTaking.setApproveTime(new Date());
        
        // 获取完整的盘点单信息
        CkStockTaking stockTaking = ckStockTakingMapper.selectCkStockTakingById(ckStockTaking.getTakingId());
        if (stockTaking == null) {
            throw new RuntimeException("盘点单不存在");
        }
        
        // 检查盘点单状态，只有进行中状态才能审核
        if (!"1".equals(stockTaking.getStatus())) {
            throw new RuntimeException("只能审核进行中状态的盘点单");
        }
        
        // 根据审核状态设置盘点状态
        String status = "1"; // 默认为进行中
        if ("2".equals(ckStockTaking.getApproveStatus())) {
            status = "2"; // 审核通过，设置为已完成
            
            // 设置盘点结束时间
            stockTaking.setEndTime(new Date());
            ckStockTakingMapper.updateCkStockTaking(stockTaking);
            
            // 审核通过，调整库存
            if ("Y".equals(stockTaking.getFrozenFlag())) {
                // 解冻库存
                unfreezeInventory(ckStockTaking.getTakingId());
                
                // 调整库存
                adjustInventory(ckStockTaking.getTakingId());
            }
        } else if ("3".equals(ckStockTaking.getApproveStatus())) {
            status = "3"; // 审核驳回，设置为已取消
            
            // 设置盘点结束时间
            stockTaking.setEndTime(new Date());
            ckStockTakingMapper.updateCkStockTaking(stockTaking);
            
            // 审核驳回，解冻库存但不调整
            if ("Y".equals(stockTaking.getFrozenFlag())) {
                unfreezeInventory(ckStockTaking.getTakingId());
            }
        }
        
        return ckStockTakingMapper.updateStatus(ckStockTaking.getTakingId(), status, ckStockTaking.getApproveStatus());
    }
    
    /**
     * 查询盘点明细列表
     * 
     * @param takingId 盘点ID
     * @return 盘点明细集合
     */
    @Override
    public List<CkStockTakingResult> selectCkStockTakingResultList(Long takingId) {
        CkStockTakingResult query = new CkStockTakingResult();
        query.setTakingId(takingId);
        return ckStockTakingResultMapper.selectCkStockTakingResultList(query);
    }
    
    /**
     * 取消盘点单
     * 
     * @param takingId 盘点ID
     * @return 结果
     */
    @Override
    @Transactional
    public int cancelCkStockTaking(Long takingId) {
        // 获取盘点单信息
        CkStockTaking stockTaking = ckStockTakingMapper.selectCkStockTakingById(takingId);
        if (stockTaking == null) {
            throw new RuntimeException("盘点单不存在");
        }
        
        // 检查盘点单状态，只有草稿或进行中状态才能取消
        if (!"0".equals(stockTaking.getStatus()) && !"1".equals(stockTaking.getStatus())) {
            throw new RuntimeException("只能取消草稿或进行中状态的盘点单");
        }
        
        // 设置盘点结束时间
        stockTaking.setEndTime(new Date());
        ckStockTakingMapper.updateCkStockTaking(stockTaking);
        
        // 如果已冻结库存，则解冻
        if ("Y".equals(stockTaking.getFrozenFlag()) && "1".equals(stockTaking.getStatus())) {
            unfreezeInventory(takingId);
        }
        
        // 更新盘点单状态为已取消
        return ckStockTakingMapper.updateStatus(takingId, "3", "3");
    }
    
    /**
     * 冻结库存
     * 
     * @param takingId 盘点ID
     */
    private void freezeInventory(Long takingId) {
        // 获取盘点明细
        List<CkStockTakingResult> details = ckStockTakingResultMapper.selectCkStockTakingResultByTakingId(takingId);
        if (details != null && !details.isEmpty()) {
            for (CkStockTakingResult detail : details) {
                // 这里应该调用库存服务的冻结方法，但由于限制只能使用两张表，
                // 所以我们只记录操作类型，实际不修改库存表
                detail.setOperationType("freeze");
                detail.setOperationContent("盘点冻结库存");
                detail.setUpdateTime(new Date());
                ckStockTakingResultMapper.updateCkStockTakingResult(detail);
            }
        }
    }
    
    /**
     * 解冻库存
     * 
     * @param takingId 盘点ID
     */
    private void unfreezeInventory(Long takingId) {
        // 获取盘点明细
        List<CkStockTakingResult> details = ckStockTakingResultMapper.selectCkStockTakingResultByTakingId(takingId);
        if (details != null && !details.isEmpty()) {
            for (CkStockTakingResult detail : details) {
                // 这里应该调用库存服务的解冻方法，但由于限制只能使用两张表，
                // 所以我们只记录操作类型，实际不修改库存表
                detail.setOperationType("unfreeze");
                detail.setOperationContent("盘点解冻库存");
                detail.setUpdateTime(new Date());
                ckStockTakingResultMapper.updateCkStockTakingResult(detail);
            }
        }
    }
    
    /**
     * 调整库存
     * 
     * @param takingId 盘点ID
     */
    private void adjustInventory(Long takingId) {
        // 获取盘点明细
        List<CkStockTakingResult> details = ckStockTakingResultMapper.selectCkStockTakingResultByTakingId(takingId);
        if (details != null && !details.isEmpty()) {
            for (CkStockTakingResult detail : details) {
                // 只有存在差异的物料才需要调整
                if (detail.getDifferenceQuantity() != null && detail.getDifferenceQuantity().doubleValue() != 0) {
                    // 这里应该调用库存服务的调整方法，但由于限制只能使用两张表，
                    // 所以我们只记录操作类型，实际不修改库存表
                    if (detail.getDifferenceQuantity().doubleValue() > 0) {
                        detail.setOperationType("adjust_increase");
                        detail.setOperationContent("盘点调整库存增加: " + detail.getDifferenceQuantity());
                    } else {
                        detail.setOperationType("adjust_decrease");
                        detail.setOperationContent("盘点调整库存减少: " + detail.getDifferenceQuantity());
                    }
                    detail.setUpdateTime(new Date());
                    ckStockTakingResultMapper.updateCkStockTakingResult(detail);
                }
            }
        }
    }
} 